<template>
    <view v-if="showClone">
        <view class="container l-class" @touchmove.stop.prevent="trueFun" :style="'z-index: ' + zIndex + ';'">
            <view class="clip-wrapper" @touchstart="clipTouchStart" @touchmove="clipTouchMove" @touchend="clipTouchEnd">
                <view class="clip-content">
                    <view class="clip-content-top bg-transparent" :style="'height: ' + cutY + 'px;transition-property: ' + (cutAnimation ? '' : 'background')"></view>
                    <view class="clip-content-middle" :style="'height: ' + clipHeight + 'px;'">
                        <view class="clip-content-middle-left bg-transparent" :style="'width: ' + cutX + 'px;transition-property: ' + (cutAnimation ? '' : 'background')"></view>
                        <view
                            class="clip-content-middle-center"
                            :style="'width: ' + clipWidth + 'px;height: ' + clipHeight + 'px;transition-property: ' + (cutAnimation ? '' : 'background')"
                        >
                            <view
                                :class="'clip-edge clip-edge-' + (index < 2 ? 'top' : 'bottom') + '-' + (index === 0 || index === 2 ? 'left' : 'right')"
                                :style="
                                    'left: ' +
                                    (index === 0 || index === 2 ? 0 : 'auto') +
                                    ';right: ' +
                                    (index === 1 || index === 3 ? 0 : 'auto') +
                                    ';top: ' +
                                    (index < 2 ? 0 : 'auto') +
                                    ';bottom: ' +
                                    (index > 1 ? 0 : 'auto')
                                "
                                v-for="(item, index) in 4"
                                :key="index"
                            ></view>
                        </view>
                        <view class="clip-content-middle-right flex-auto bg-transparent" :style="'transition-property: ' + (cutAnimation ? '' : 'background')"></view>
                    </view>
                    <view class="clip-content-footer flex-auto bg-transparent" :style="'transition-property: ' + (cutAnimation ? '' : 'background')"></view>
                </view>
            </view>

            <image
                class="cropper-image"
                @error="imageLoad"
                @load="imageLoad"
                @touchstart="imageTouchStart"
                @touchmove="imageTouchMove"
                @touchend="imageTouchEnd"
                :src="imageUrlClone"
                mode="widthFix"
                v-if="imageUrlClone"
                :style="
                    'width: ' +
                    (imageWidth ? imageWidth + 'px' : 'auto') +
                    ';height: ' +
                    (imageHeight ? imageHeight + 'px' : 'auto') +
                    ';transform: translate3d(' +
                    (imageLeft - imageWidth / 2) +
                    'px, ' +
                    (imageTop - imageHeight / 2) +
                    'px,0) scale(' +
                    scale +
                    ') rotate(' +
                    angle +
                    'deg); transition-duration: ' +
                    (cutAnimation ? 0.35 : 0) +
                    's;'
                "
            />

            <canvas
                canvas-id="image-clipper"
                id="image-clipper"
                :disable-scroll="true"
                :style="'width: ' + CANVAS_WIDTH * scaleRatio + 'px; height:' + CANVAS_HEIGHT * scaleRatio + 'px;'"
                class="clipper-canvas"
            ></canvas>

            <view class="footer-tools">
                <view class="tools-icon">
                    <image :src="checkImageIcon" mut-bind:tap="uploadImage" v-if="checkImage" />
                    <image :src="rotateAlongIcon" mut-bind:tap="rotate" data-type="along" v-if="rotateAlong" />
                    <image :src="rotateInverseIcon" mut-bind:tap="rotate" data-type="inverse" v-if="rotateInverse" />
                    <image :src="sureIcon" mut-bind:tap="getImageData" v-if="sure" />
                    <image :src="closeIcon" mut-bind:tap="close" v-if="close" />
                </view>
                <slot></slot>
            </view>
        </view>
    </view>
</template>

<script>
import dataUtil from '../core/utils/data-util';
import eventUtil from '../core/utils/event-util';
import { determineDirection, calcImageOffset, calcImageScale, calcImageSize, calcPythagoreanTheorem, clipTouchMoveOfCalculate, imageTouchMoveOfCalcOffset } from './calculate';
const detail = true;
const IMAGE_TYPE = {
    base64: 'base64',
    url: 'url'
};
export default {
    unicomGroup: ['image-clipper-tools'],
    data() {
        return {
            CANVAS_WIDTH: 0,
            CANVAS_HEIGHT: 0,
            cutX: 0,
            cutY: 0,
            clipWidth: 0,
            clipHeight: 0,
            cutAnimation: false,
            imageWidth: 0,
            imageHeight: 0,
            imageTop: 0,
            imageLeft: 0,
            scale: 1,
            angle: 0,
            _SYS_INFO: {},
            _MOVE_THROTTLE: null,
            _MOVE_THROTTLE_FLAG: true,
            _TIME_CUT_CENTER: null,
            _flagCutTouch: false,
            _flagEndTouch: false,
            _CUT_START: {},
            _cutAnimationTime: null,

            _touchRelative: [
                {
                    x: 0,
                    y: 0
                }
            ],

            _hypotenuseLength: 0,
            _ctx: null,
            showClone: '',
            imageUrlClone: ''
        };
    },
    externalClasses: ['l-class'],
    relations: {
        '../image-clipper-tools/index': {
            type: 'child'
        }
    },
    options: {
        pureDataPattern: /^_/
    },
    props: {
        show: {
            type: Boolean,
            default: false
        },
        zIndex: {
            type: Number,
            default: 99
        },
        imageUrl: {
            type: String
        },
        type: {
            type: String,
            options: ['url', 'base64'],
            default: 'url'
        },
        quality: {
            type: Number,
            default: 1
        },
        width: {
            type: Number,
            default: 400
        },
        height: {
            type: Number,
            default: 400
        },
        minWidth: {
            type: Number,
            default: 200
        },
        maxWidth: {
            type: Number,
            default: 600
        },
        minHeight: {
            type: Number,
            default: 200
        },
        maxHeight: {
            type: Number,
            default: 600
        },
        lockWidth: {
            type: Boolean,
            default: false
        },
        lockHeight: {
            type: Boolean,
            default: false
        },
        lockRatio: {
            type: Boolean,
            default: true
        },
        scaleRatio: {
            type: Number,
            default: 1
        },
        minRatio: {
            type: Number,
            default: 0.5
        },
        maxRatio: {
            type: Number,
            default: 2
        },
        disableScale: {
            type: Number,
            default: false
        },
        disableRotate: {
            type: Number,
            default: false
        },
        limitMove: {
            type: Boolean,
            default: false
        },
        checkImage: {
            type: Boolean,
            default: true
        },
        checkImageIcon: {
            type: String,
            default: '/static/miniprogram_npm/lin-ui/image-clipper/images/photo.png'
        },
        rotateAlong: {
            type: Boolean,
            default: true
        },
        rotateAlongIcon: {
            type: String,
            default: '/static/miniprogram_npm/lin-ui/image-clipper/images/rotate-along.png'
        },
        rotateInverse: {
            type: Boolean,
            default: true
        },
        rotateInverseIcon: {
            type: String,
            default: '/static/miniprogram_npm/lin-ui/image-clipper/images/rotate-inverse.png'
        },
        sure: {
            type: Boolean,
            default: true
        },
        sureIcon: {
            type: String,
            default: '/static/miniprogram_npm/lin-ui/image-clipper/images/sure.png'
        },
        close: {
            type: Boolean,
            default: true
        },
        closeIcon: {
            type: String,
            default: '/static/miniprogram_npm/lin-ui/image-clipper/images/close.png'
        },
        rotateAngle: {
            type: Number,
            default: 90
        }
    },
    watch: {
        imageUrl: function (t) {
            if (t) {
                this.imageReset();
                uni.showLoading({
                    title: '请稍候...',
                    mask: true
                });
                uni.getImageInfo({
                    src: t,
                    success: (t) => {
                        this.imgComputeSize(t.width, t.height);
                        if (this.limitMove) {
                            this.imgMarginDetectionScale();
                            eventUtil.emit(this, 'linimageready', t);
                        }
                    },
                    fail: () => {
                        this.imgComputeSize();
                        if (this.limitMove) {
                            this.imgMarginDetectionScale();
                        }
                    }
                });
            }
        },

        clipWidth_clipHeight: {
            deep: true,
            immediate: true,

            handler: function (newValue, oldValue) {
                const { t, e } = newValue;

                let { minWidth: i, minHeight: a } = this;
                i /= 2;
                a /= 2;
                if (t < i) {
                    dataUtil.setDiffData(this, {
                        clipWidth: i
                    });
                }
                if (e < a) {
                    dataUtil.setDiffData(this, {
                        clipHeight: a
                    });
                }
                this.computeCutSize();
            }
        },

        rotateAngle: function (t) {
            dataUtil.setDiffData(this, {
                cutAnimation: true,
                angle: t
            });
        },

        angle: function (t) {
            this.moveStop();
            const { limitMove: e } = this;
            if (e && t % 90) {
                dataUtil.setDiffData(this, {
                    angle: 90 * Math.round(t / 90)
                });
            }
            this.imgMarginDetectionScale();
        },

        cutAnimation: function (t) {
            clearTimeout(this._cutAnimationTime);
            if (t) {
                let t = setTimeout(() => {
                    dataUtil.setDiffData(this, {
                        cutAnimation: false
                    });
                }, 260);
                dataUtil.setDiffData(this, {
                    _cutAnimationTime: t
                });
            }
        },

        limitMove: function (t) {
            if (t) {
                if (this.angle % 90) {
                    dataUtil.setDiffData(this, {
                        angle: 90 * Math.round(this.angle / 90)
                    });
                }
                this.imgMarginDetectionScale();
            }
        },

        cutY_cutX: {
            deep: true,
            immediate: true,

            handler: function (newValue, oldValue) {
                this.cutDetectionPosition();
            }
        },

        width_height: {
            deep: true,
            immediate: true,

            handler: function (newValue, oldValue) {
                const { t, e } = newValue;

                if (t !== this.width) {
                    dataUtil.setDiffData(this, {
                        clipWidth: t / 2
                    });
                }
                if (e !== this.height) {
                    dataUtil.setDiffData(this, {
                        clipHeight: e / 2
                    });
                }
            }
        }
    },
    methods: {
        ready() {
            const t = uni.getSystemInfoSync();
            this.setData({
                _SYS_INFO: t
            });
            this.setCutInfo();
            this.setCutCenter();
            this.computeCutSize();
            this.cutDetectionPosition();
        },

        setCutInfo() {
            const { width: t, height: e } = this;
            const { _SYS_INFO: i } = this;
            const a = t / 2;
            const s = e / 2;
            const o = (i.windowHeight - s) / 2;
            const h = (i.windowWidth - a) / 2;
            const l = i.windowWidth / 2;
            const n = i.windowHeight / 2;
            const c = uni.createCanvasContext('image-clipper', this);
            this.setData({
                clipWidth: a,
                clipHeight: s,
                cutX: h,
                cutY: o,
                CANVAS_HEIGHT: s,
                CANVAS_WIDTH: a,
                _ctx: c,
                imageLeft: l,
                imageTop: n
            });
        },

        setCutCenter() {
            const { sysInfo: t, clipHeight: e, clipWidth: i, imageTop: a, imageLeft: s } = this;
            let o = t || uni.getSystemInfoSync();
            let h = 0.5 * (o.windowHeight - e);
            let l = 0.5 * (o.windowWidth - i);
            this.setData({
                imageTop: a - this.cutY + h,
                imageLeft: s - this.cutX + l,
                cutY: h,
                cutX: l
            });
        },

        clipTouchStart(t) {
            if (!this.imageUrlClone) {
                return void uni.showToast({
                    title: '请选择图片',
                    icon: 'none'
                });
            }
            const e = t.touches[0].clientX;
            const i = t.touches[0].clientY;
            const { cutX: a, cutY: s, clipWidth: o, clipHeight: h } = this;
            const l = determineDirection(a, s, o, h, e, i);
            this.moveDuring();
            const n = {
                width: o,
                height: h,
                x: e,
                y: i,
                cutY: s,
                cutX: a,
                corner: l
            };
            this.setData({
                _flagCutTouch: true,
                _flagEndTouch: true,
                _CUT_START: n
            });
        },

        clipTouchMove(t) {
            if (!this.imageUrlClone) {
                return void uni.showToast({
                    title: '请选择图片',
                    icon: 'none'
                });
            }
            const { _flagCutTouch: e, _MOVE_THROTTLE_FLAG: i } = this;
            if (e && i) {
                const { lockRatio: e, lockHeight: i, lockWidth: a } = this;
                if (e && (a || i)) {
                    return;
                }
                dataUtil.setDiffData(this, {
                    _MOVE_THROTTLE_FLAG: false
                });
                this.moveThrottle();
                const { width: s, height: o, cutX: h, cutY: l } = clipTouchMoveOfCalculate(this, t);
                if (a || i) {
                    if (a) {
                        i ||
                            dataUtil.setDiffData(this, {
                                clipHeight: o,
                                cutY: l
                            });
                    } else {
                        dataUtil.setDiffData(this, {
                            clipWidth: s,
                            cutX: h
                        });
                    }
                } else {
                    dataUtil.setDiffData(this, {
                        clipWidth: s,
                        clipHeight: o,
                        cutX: h,
                        cutY: l
                    });
                }
                this.imgMarginDetectionScale();
            }
        },

        clipTouchEnd() {
            this.moveStop();
            this.setData({
                _flagCutTouch: false
            });
        },

        moveDuring() {
            clearTimeout(this._TIME_CUT_CENTER);
        },

        moveStop() {
            clearTimeout(this._TIME_CUT_CENTER);
            const t = setTimeout(() => {
                this.cutAnimation ||
                    dataUtil.setDiffData(this, {
                        cutAnimation: true
                    });
                this.setCutCenter();
            }, 800);
            dataUtil.setDiffData(this, {
                _TIME_CUT_CENTER: t
            });
        },

        moveThrottle() {
            if ('android' === this._SYS_INFO.platform) {
                clearTimeout(this._MOVE_THROTTLE);
                const t = setTimeout(() => {
                    dataUtil.setDiffData(this, {
                        _MOVE_THROTTLE_FLAG: true
                    });
                }, 20);
                dataUtil.setDiffData(this, {
                    _MOVE_THROTTLE: t
                });
            } else {
                dataUtil.setDiffData(this, {
                    _MOVE_THROTTLE_FLAG: true
                });
            }
        },

        imageReset() {
            const t = this._SYS_INFO || uni.getSystemInfoSync();
            this.setData({
                scale: 1,
                angle: 0,
                imageTop: t.windowHeight / 2,
                imageLeft: t.windowWidth / 2
            });
        },

        imageLoad() {
            this.imageReset();
            uni.hideLoading();
            eventUtil.emit(this, 'linimageload', true);
        },

        imgComputeSize(t, e) {
            const { imageWidth: i, imageHeight: a } = calcImageSize(t, e, this);
            this.setData({
                imageWidth: i,
                imageHeight: a
            });
        },

        imgMarginDetectionScale(t) {
            if (!this.limitMove) {
                return;
            }
            const e = calcImageScale(this, t);
            this.imgMarginDetectionPosition(e);
        },

        imgMarginDetectionPosition(t) {
            if (!this.limitMove) {
                return;
            }
            const { scale: e, left: i, top: a } = calcImageOffset(this, t);
            dataUtil.setDiffData(this, {
                imageLeft: i,
                imageTop: a,
                scale: e
            });
        },

        imageTouchStart(t) {
            this.setData({
                _flagEndTouch: false
            });
            const { imageLeft: e, imageTop: i } = this;
            const a = t.touches[0].clientX;
            const s = t.touches[0].clientY;
            let o = [];
            if (1 === t.touches.length) {
                o[0] = {
                    x: a - e,
                    y: s - i
                };
                this.setData({
                    _touchRelative: o
                });
            } else {
                const h = t.touches[1].clientX;
                const l = t.touches[1].clientY;
                let n = Math.abs(a - h);
                let c = Math.abs(s - l);
                const u = calcPythagoreanTheorem(n, c);
                o = [
                    {
                        x: a - e,
                        y: s - i
                    },
                    {
                        x: h - e,
                        y: l - i
                    }
                ];
                this.setData({
                    _touchRelative: o,
                    _hypotenuseLength: u
                });
            }
        },

        imageTouchMove(t) {
            const { _flagEndTouch: e, _MOVE_THROTTLE_FLAG: i } = this;
            if (e || !i) {
                return;
            }
            const a = t.touches[0].clientX;
            const s = t.touches[0].clientY;
            dataUtil.setDiffData(this, {
                _MOVE_THROTTLE_FLAG: false
            });
            this.moveThrottle();
            this.moveDuring();
            if (1 === t.touches.length) {
                const { left: t, top: e } = imageTouchMoveOfCalcOffset(this, a, s);
                dataUtil.setDiffData(this, {
                    imageLeft: t,
                    imageTop: e
                });
                this.imgMarginDetectionPosition();
            } else {
                const e = t.touches[1].clientX;
                const i = t.touches[1].clientY;
                let o = Math.abs(a - e);
                let h = Math.abs(s - i);
                let l = calcPythagoreanTheorem(o, h);
                let n = this.scale * (l / this._hypotenuseLength);
                if (this.disableScale) {
                    n = 1;
                } else {
                    if (n <= this.minRatio) {
                        n = this.minRatio;
                    } else {
                        n = n;
                    }
                    if (n >= this.maxRatio) {
                        n = this.maxRatio;
                    } else {
                        n = n;
                    }
                    eventUtil.emit(this, 'linsizechange', {
                        imageWidth: this.imageWidth * n,
                        imageHeight: this.imageHeight * n
                    });
                }
                this.imgMarginDetectionScale(n);
                dataUtil.setDiffData(this, {
                    _hypotenuseLength: Math.sqrt(Math.pow(o, 2) + Math.pow(h, 2)),
                    scale: n
                });
            }
        },

        imageTouchEnd() {
            dataUtil.setDiffData(this, {
                _flagEndTouch: true
            });
            this.moveStop();
        },

        cutDetectionPosition() {
            const { cutX: t, cutY: e, _SYS_INFO: i, clipHeight: a, clipWidth: s } = this;
            let o = () => {
                if (e < 0) {
                    dataUtil.setDiffData(this, {
                        cutY: 0
                    });
                }
                if (e > i.windowHeight - a) {
                    dataUtil.setDiffData(this, {
                        cutY: i.windowHeight - a
                    });
                }
            };
            let h = () => {
                if (t < 0) {
                    dataUtil.setDiffData(this, {
                        cutX: 0
                    });
                }
                if (t > i.windowWidth - s) {
                    dataUtil.setDiffData(this, {
                        cutX: i.windowWidth - s
                    });
                }
            };
            if (null === e && null === t) {
                let t = 0.5 * (i.windowHeight - a);
                let e = 0.5 * (i.windowWidth - s);
                dataUtil.setDiffData(this, {
                    cutX: e,
                    cutY: t
                });
            } else {
                if (null !== e && null !== t) {
                    o();
                    h();
                } else {
                    if (null !== e && null === t) {
                        o();
                        dataUtil.setDiffData(this, {
                            cutX: (i.windowWidth - s) / 2
                        });
                    } else {
                        if (null === e && null !== t) {
                            h();
                            dataUtil.setDiffData(this, {
                                cutY: (i.windowHeight - a) / 2
                            });
                        }
                    }
                }
            }
        },

        computeCutSize() {
            const { clipHeight: t, clipWidth: e, _SYS_INFO: i, cutX: a, cutY: s } = this;
            if (e > i.windowWidth) {
                dataUtil.setDiffData(this, {
                    clipWidth: i.windowWidth
                });
            } else {
                if (e + a > i.windowWidth) {
                    dataUtil.setDiffData(this, {
                        cutX: i.windowWidth - a
                    });
                }
            }
            if (t > i.windowHeight) {
                dataUtil.setDiffData(this, {
                    clipHeight: i.windowHeight
                });
            } else {
                if (t + s > i.windowHeight) {
                    dataUtil.setDiffData(this, {
                        cutY: i.windowHeight - s
                    });
                }
            }
        },

        getImageData() {
            if (!this.imageUrlClone) {
                return void uni.showToast({
                    title: '请选择图片',
                    icon: 'none'
                });
            }
            uni.showLoading({
                title: '加载中'
            });
            const { clipHeight: t, clipWidth: e, _ctx: i, scale: a, imageLeft: s, imageTop: o, cutX: h, cutY: l, angle: n } = this;
            let { CANVAS_HEIGHT: c, CANVAS_WIDTH: u } = this;
            const { scaleRatio: g, imageUrlClone: r, quality: d, type: m } = this;
            const p = () => {
                const c = this.imageWidth * a * g;
                const u = this.imageHeight * a * g;
                const p = s - h;
                const f = o - l;
                i.translate(p * g, f * g);
                i.rotate((n * Math.PI) / 180);
                i.drawImage(r, -c / 2, -u / 2, c, u);
                i.draw(false, () => {
                    let i = {
                        width: e * g,
                        height: Math.round(t * g),
                        destWidth: e * g,
                        destHeight: Math.round(t) * g,
                        fileType: 'png',
                        quality: d
                    };
                    let a = {
                        url: '',
                        base64: '',
                        width: e * g,
                        height: t * g
                    };
                    if (IMAGE_TYPE.base64 === m) {
                        uni.canvasGetImageData({
                            canvasId: 'image-clipper',
                            x: 0,
                            y: 0,
                            width: e * g,
                            height: Math.round(t * g),
                            success: (t) => {
                                const e = new Uint8Array(t.data);
                                const i = uni.arrayBufferToBase64(e);
                                a.url = i;
                                a.base64 = i;
                                uni.hideLoading();
                                eventUtil.emit(this, 'linclip', a);
                            }
                        });
                    } else {
                        uni.canvasToTempFilePath(
                            {
                                ...i,
                                canvasId: 'image-clipper',
                                success: (t) => {
                                    a.url = t.tempFilePath;
                                    a.base64 = t.tempFilePath;
                                    uni.hideLoading();
                                    eventUtil.emit(this, 'linclip', a);
                                },
                                fail(t) {
                                    throw t;
                                }
                            },
                            this
                        );
                    }
                });
            };
            if (u !== e || c !== t) {
                u = e;
                c = t;
                i.draw();
                setTimeout(() => {
                    p();
                }, 100);
            } else {
                p();
            }
        },

        uploadImage() {
            uni.chooseImage({
                count: 1,
                sizeType: ['original', 'compressed'],
                sourceType: ['album', 'camera'],
                success: (t) => {
                    const e = t.tempFilePaths;
                    this.setData({
                        imageUrlClone: e
                    });
                }
            });
        },

        rotate(t) {
            if (this.disableRotate) {
                return;
            }
            if (!this.imageUrlClone) {
                return void uni.showToast({
                    title: '请选择图片',
                    icon: 'none'
                });
            }
            const { rotateAngle: e } = this;
            const i = this.angle;
            if ('along' === t.currentTarget.dataset.type) {
                this.setData({
                    angle: i + e
                });
            } else {
                this.setData({
                    angle: i - e
                });
            }
            eventUtil.emit(this, 'linrotate', {
                currentDeg: this.angle
            });
        },

        close() {
            this.setData({
                showClone: false
            });
        }
    },
    mounted() {
        // 处理小程序 ready 生命周期
        this.$nextTick(() => this.ready());
    },
    created: function () {}
};
</script>
<style>
.container {
    width: 100vw;
    height: 100vh;
    background-color: rgba(0, 0, 0, 0.6);
    position: fixed;
    top: 0;
    left: 0;
    z-index: 1;
}
.container .clip-wrapper {
    position: absolute;
    width: 100vw;
    height: 100vh;
}
.container .clip-wrapper .clip-content {
    width: 100vw;
    height: 100vh;
    position: absolute;
    z-index: 99;
    display: flex;
    flex-direction: column;
    pointer-events: none;
}
.container .clip-wrapper .clip-content .flex-auto {
    flex: auto;
}
.container .clip-wrapper .clip-content .clip-content-footer,
.container .clip-wrapper .clip-content .clip-content-top {
    width: 100%;
    pointer-events: none;
}
.container .clip-wrapper .clip-content .clip-content-middle {
    width: 100%;
    height: 400rpx;
    display: flex;
    box-sizing: border-box;
}
.container .clip-wrapper .clip-content .clip-content-middle .clip-content-middle-left,
.container .clip-wrapper .clip-content .clip-content-middle .clip-content-middle-right {
    height: 100%;
}
.container .clip-wrapper .clip-content .clip-content-middle .clip-content-middle-center {
    position: relative;
    border: 1px solid;
    box-sizing: border-box;
}
.container .clip-wrapper .clip-content .clip-content-middle .clip-content-middle-center .clip-edge {
    position: absolute;
    left: 6rpx;
    width: 34rpx;
    height: 34rpx;
    border: 2rpx solid #fff;
    pointer-events: auto;
    box-sizing: border-box;
}
.container .clip-wrapper .clip-content .clip-content-middle .clip-content-middle-center .clip-edge.clip-edge-top-left {
    border-bottom-width: 0 !important;
    border-right-width: 0 !important;
}
.container .clip-wrapper .clip-content .clip-content-middle .clip-content-middle-center .clip-edge.clip-edge-top-right {
    border-bottom-width: 0 !important;
    border-left-width: 0 !important;
}
.container .clip-wrapper .clip-content .clip-content-middle .clip-content-middle-center .clip-edge.clip-edge-bottom-left {
    border-top-width: 0 !important;
    border-right-width: 0 !important;
}
.container .clip-wrapper .clip-content .clip-content-middle .clip-content-middle-center .clip-edge.clip-edge-bottom-right {
    border-top-width: 0 !important;
    border-left-width: 0 !important;
}
.container .clip-wrapper .bg-transparent {
    background-color: rgba(0, 0, 0, 0.6);
    transition-duration: 0.35s;
}
.container .cropper-image {
    width: 100%;
    border-style: none;
    position: absolute;
    top: 0;
    left: 0;
    z-index: 2;
    -webkit-backface-visibility: hidden;
    backface-visibility: hidden;
    transform-origin: center;
}
.container .clipper-canvas {
    position: fixed;
    z-index: 10;
    left: -2000px;
    top: -2000px;
    pointer-events: none;
}
.container .footer-tools {
    position: absolute;
    left: 0;
    bottom: 0;
    width: 100%;
    z-index: 99;
}
.container .footer-tools .tools-icon {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    padding: 20rpx 40rpx;
    box-sizing: border-box;
}
.container .footer-tools .tools-icon image {
    display: block;
    width: 50rpx;
    height: 50rpx;
}
</style>
